package com.jml.dubbo.server.rpc;

import java.util.HashMap;
import java.util.Map;

import com.jml.dubbo.RpcAnnotation;
import com.jml.dubbo.server.handler.DubboServerHandler;
import com.jml.dubbo.server.marshalling.MarshallingCodeCFactory;
import com.jml.dubbo.server.registr.ServiceRegistration;
import com.jml.dubbo.server.registr.ServiceRegistrationImpl;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;


public class JmlRpcServer {

    private ServiceRegistration serviceRegistration;
    /**
     * host
     */
    private String host;
    /**
     * 端口号
     */
    private int port;


    private Map<String, Object> hanlderMap = new HashMap<>();

    public JmlRpcServer(String host, int port) {
        this.host = host;
        this.port = port;
        serviceRegistration = new ServiceRegistrationImpl();
    }

    /**
     * 核心流程：
     * <p>
     * bind().将我们本地服务注册到zk上
     * 启动我们netty服务器端实现监听
     */
    public void bind(Object object) {
        //获取类上是否有加上rpc注解
        RpcAnnotation declaredAnnotation = object.getClass().getDeclaredAnnotation(RpcAnnotation.class);
        if (declaredAnnotation == null) {
            // 抛出异常
            return;
        }
        // 获取到了service name
        String serviceName = declaredAnnotation.value().getName();
        String serviceAddres = "mayikt://" + host + ":" + port;
        serviceRegistration.registr(serviceName, serviceAddres);
        hanlderMap.put(serviceName, object);
    }
    // 消费调用生产者：mayikt://192.168.1.1:8080/ com.mayikt.service.userService.getUser 参数、类型返回值

    public void start(Object object) {
        // 将我们的服务注册到zk上
        bind(object);
        // 启动我们的netty服务
        nettyStat();

    }

    private void nettyStat() {
        /**
         *  客户端创建两个线程池组分别为 boss线程组和工作线程组
         */
        // 用于接受客户端连接的请求 （并没有处理请求）
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        // 用于处理客户端连接的读写操作
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
        // 用于创建我们的ServerBootstrap
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        // 监听我们的handlere
                        socketChannel.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
                        socketChannel.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
                        socketChannel.pipeline().addLast(new DubboServerHandler(hanlderMap));
                    }
                });
        //  绑定我们的端口号码
        try {
            // 绑定端口号，同步等待成功
            ChannelFuture future = serverBootstrap.bind(port).sync();
            System.out.println("服务器启动成功：" + port);
            // 等待服务器监听端口
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            // 优雅的关闭连接
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}
